﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ChartDirector;
using System.Text.RegularExpressions;
using System.Collections;

namespace GoodTrader.GTChart
{
    public partial class frmFutureChart : Form
    {
        public frmFutureChart()
        {
            InitializeComponent();
        }

        GTWave.GTWaveManager m_WaveMgr = new GTWave.GTWaveManager();

        // 이동평균을 위한 여분의 데이터를 설정한다. 이 데이터는 이동평균을 위해서만 사용되고 차트에는 나타나지 않는다.
        private int mExtraPoints = 20;
        private int mIndex = 10;
   
        private GTDownload.CpDataSet mCpDataSetObj = null;
        public GTDownload.CpDataSet CpDataSetObj
        {
            get { return mCpDataSetObj; }
            set { mCpDataSetObj = value; }
        }

        double[] dataSTime = null;
        double[] dataHigh = null;
        double[] dataLow = null;
        double[] dataClose = null;
        double[] dataOpen = null;
        double[] dataAmount = null;
        double[] dataCTime = null;
        DateTime[] dataSysTime = null;

        // Will set to true at the end of initialization - prevents events from firing before the
        // controls are properly initialized.
        private bool hasFinishedInitialization = false;

        private void frmFutureChart_Load(object sender, EventArgs e)
        {
            hasFinishedInitialization = true;
            //drawChart(winChartViewer1);
            InitTimer();
            // 차트 확대 축소와 관련된 사항을 초기화 한다.
            initChartViewer(chartCtrl);
            // Some Visual Studio versions do not expose the MouseWheel event in the Property window, so we
            // need to set up the event handler with our own code.
            chartCtrl.MouseWheel += new MouseEventHandler(chartCtrl_MouseWheel);

            // Trigger the ViewPortChanged event to draw the chart
            chartCtrl.updateViewPort(true, true);
            InitSource();
            comboSource.SelectedIndex = 0;
            comboTrendLine.SelectedIndex = 3;
        }

        /**
         * @brief 이 함수는 옵션 코드를 가져와서 콤보박스에 넣어준다.
         */ 
        private void InitSource()
        {
            comboSource.Items.Add("주간선물");
            comboSource.Items.Add("야간선물");

            for(int i = 0; i < 50; i++)
            {
                comboTrendLine.Items.Add(i.ToString());
            }
        }

        private void chartCtrl_MouseEnter(object sender, EventArgs e)
        {
            // Save the original active control and set the WinChartViewer to be the active control, so that
            // the WinChartViewer can receive the mouse wheel event.
            activeControl = chartCtrl.FindForm().ActiveControl;
            chartCtrl.FindForm().ActiveControl = chartCtrl;
        }

        private void chartCtrl_MouseLeave(object sender, EventArgs e)
        {
            // Restore the original active control.
            chartCtrl.FindForm().ActiveControl = activeControl;
        }

        private void chartCtrl_MouseMovePlotArea(object sender, MouseEventArgs e)
        {
            WinChartViewer viewer = (WinChartViewer)sender;
            trackFinance((MultiChart)viewer.Chart, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY);
            viewer.updateDisplay();
        }

        //
        // Draw finance chart track line with legend
        //
        private void trackFinance(MultiChart m, int mouseX, int mouseY)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = m.initDynamicLayer();

            //d.line(0, 0, 100, 100, 100, 2);

            // It is possible for a FinanceChart to be empty, so we need to check for it.
            if (m.getChartCount() == 0)
            {
                return;
            }

            
            // 여분의 점이 있기때문에 현재 x좌표를 참조할 때는 원래 데이터에서 여분의 데이터를 더한 값이 현재 값이 된다.
            // 예를 들면 데이터가 450개이고 여분데이터를 20으로 설정했을 때, 현재 인덱스가 45 이면 원래값은 45 + 20을 해야 원래값을 가져올 수 있다.
            // Get the data x-value that is nearest to the mouse
            int xValue = (int)(((XYChart)m.getChart(0)).getNearestXValue(mouseX));
            

            // Iterate the XY charts (main price chart and indicator charts) in the FinanceChart
            XYChart c = null;
            for (int i = 0; i < m.getChartCount(); ++i)
            {
                c = (XYChart)m.getChart(i);

                // Variables to hold the legend entries
                string ohlcLegend = "";
                ArrayList legendEntries = new ArrayList();

                // Iterate through all layers to find the highest data point
                for (int j = 0; j < c.getLayerCount(); ++j)
                {
                    Layer layer = c.getLayerByZ(j);
                    int xIndex = layer.getXIndexOf(xValue);
                    int dataSetCount = layer.getDataSetCount();

                    // In a FinanceChart, only layers showing OHLC data can have 4 data sets
                    if (dataSetCount == 4)
                    {
                        double highValue = layer.getDataSet(0).getValue(xIndex);
                        double lowValue = layer.getDataSet(1).getValue(xIndex);
                        double openValue = layer.getDataSet(2).getValue(xIndex);
                        double closeValue = layer.getDataSet(3).getValue(xIndex);

                        if (closeValue != Chart.NoValue)
                        {

                            // Build the OHLC legend
                            ohlcLegend = "xIndex :: " + xIndex.ToString() + "Open: " + c.formatValue(openValue, "{value|P4}") + ", High: " +
                                c.formatValue(highValue, "{value|P4}") + ", Low: " + c.formatValue(lowValue,
                                "{value|P4}") + ", Close: " + c.formatValue(closeValue, "{value|P4}");

                            // We also draw an upward or downward triangle for up and down days and the %
                            // change
                            double lastCloseValue = layer.getDataSet(3).getValue(xIndex - 1);
                            if (lastCloseValue != Chart.NoValue)
                            {
                                double change = closeValue - lastCloseValue;
                                double percent = change * 100 / closeValue;
                                string symbol = ((change >= 0) ?
                                    "<*font,color=008800*><*img=@triangle,width=8,color=008800*>" :
                                    "<*font,color=CC0000*><*img=@invertedtriangle,width=8,color=CC0000*>");

                                ohlcLegend = ohlcLegend + "  " + symbol + " " + c.formatValue(change,
                                    "{value|P4}") + " (" + c.formatValue(percent, "{value|2}") + "%)<*/font*>"
                                    ;
                            }

                            // Use a <*block*> to make sure the line does not wrap within the legend entry
                            ohlcLegend = "<*block*>" + ohlcLegend + "      <*/*>";
                        }
                    }
                    else
                    {
                        // Iterate through all the data sets in the layer
                        for (int k = 0; k < layer.getDataSetCount(); ++k)
                        {
                            ChartDirector.DataSet dataSet = layer.getDataSetByZ(k);

                            string name = dataSet.getDataName();
                            double value = dataSet.getValue(xIndex);
                            if ((!string.IsNullOrEmpty(name)) && (value != Chart.NoValue))
                            {

                                // In a FinanceChart, the data set name consists of the indicator name and its
                                // latest value. It is like "Vol: 123M" or "RSI (14): 55.34". As we are
                                // generating the values dynamically, we need to extract the indictor name
                                // out, and also the volume unit (if any).

                                // The unit character, if any, is the last character and must not be a digit.
                                string unitChar = name.Substring(name.Length - 1);
                                if (unitChar.CompareTo("0") >= 0 && unitChar.CompareTo("9") <= 0)
                                {
                                    unitChar = "";
                                }

                                // The indicator name is the part of the name up to the colon character.
                                int delimiterPosition = name.IndexOf(":");
                                if (delimiterPosition != -1)
                                {
                                    name = name.Substring(0, delimiterPosition);
                                }

                                // In a FinanceChart, if there are two data sets, it must be representing a
                                // range.
                                if (dataSetCount == 2)
                                {
                                    // We show both values in the range in a single legend entry
                                    value = layer.getDataSet(0).getValue(xIndex);
                                    double value2 = layer.getDataSet(1).getValue(xIndex);
                                    name = name + ": " + c.formatValue(Math.Min(value, value2), "{value|P3}")
                                         + " - " + c.formatValue(Math.Max(value, value2), "{value|P3}");
                                }
                                else
                                {
                                    // In a FinanceChart, only the layer for volume bars has 3 data sets for
                                    // up/down/flat days
                                    if (dataSetCount == 3)
                                    {
                                        // The actual volume is the sum of the 3 data sets.
                                        value = layer.getDataSet(0).getValue(xIndex) + layer.getDataSet(1
                                            ).getValue(xIndex) + layer.getDataSet(2).getValue(xIndex);
                                    }

                                    // Create the legend entry
                                    name = name + " : " + c.formatValue(value, "{value|P3}") + unitChar;
                                }

                                // Build the legend entry, consist of a colored square box and the name (with
                                // the data value in it).
                                legendEntries.Add("<*block*><*img=@square,width=8,edgeColor=000000,color=" +
                                    dataSet.getDataColor().ToString("x") + "*> " + name + "<*/*>");
                            }
                        }
                    }
                }

                // Get the plot area position relative to the entire FinanceChart
                PlotArea plotArea = c.getPlotArea();
                int offsetX = c.getAbsOffsetX();
                int offsetY = c.getAbsOffsetY();
                int plotAreaLeftX = plotArea.getLeftX() + offsetX;
                int plotAreaTopY = plotArea.getTopY() + offsetY;

                double yValue = c.getYValue(mouseY, c.yAxis());

                // The legend is formed by concatenating the legend entries.
                legendEntries.Reverse();
                string legendText = String.Join("      ", (string[])legendEntries.ToArray(typeof(string)));

                // Add the date and the ohlcLegend (if any) at the beginning of the legend
                legendText = "<*block,valign=top,maxWidth=" + (plotArea.getWidth() - 5) +
                    "*><*font=Arial Bold*>[" + c.xAxis().getFormattedLabel(xValue, "mmm dd, yyyy") +
                    "]<*/font*>      " + ohlcLegend + legendText;

                // Draw a vertical track line at the x-position
                //d.vline(plotAreaTopY, plotAreaTopY + plotArea.getHeight(), c.getXCoor(xValue) + c.getAbsOffsetX(), d.dashLineColor(0x000000, 0x0101));
                int plotHeight = plotArea.getHeight();
                int plotWidth = plotArea.getWidth();
                int width = plotWidth + 0;
                //d.vline(plotAreaTopY, plotAreaTopY + plotHeight, c.getXCoor(xValue) + c.getAbsOffsetX(), d.dashLineColor(0x000000, 0x0101));
                //d.hline(plotArea.getLeftX(), plotArea.getRightX(), c.getYCoor(yValue) + c.getAbsOffsetY(), d.dashLineColor(0x000000, 0x0101));
                // Draw a vertical track line at the x-position
                d.vline(plotAreaTopY, plotAreaTopY + plotArea.getHeight(), c.getXCoor(xValue) +
                    c.getAbsOffsetX(), d.dashLineColor(0x000000, 0x0101));

                // Draw a vertical track line at the x-position
                d.hline(plotArea.getLeftX(), plotArea.getRightX(), c.getYCoor(yValue) +
                    c.getAbsOffsetY(), d.dashLineColor(0x000000, 0x0101));

                // Display the legend on the top of the plot area
                TTFText t = d.text(legendText, "Arial", 8);
                t.draw(plotAreaLeftX + 5, plotAreaTopY + 13, 0x000000, Chart.TopLeft);


                // Draw y-axis label
                string label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + c.formatValue(c.getYValue(
                    mouseY, c.yAxis()), "{value|P4}") + "<*/*>";
                TTFText tAxis = d.text(label, "Arial Bold", 8);
                tAxis.draw(plotArea.getLeftX() - 5, mouseY, 0x000000, Chart.Right);
                Layer topLayer = c.getLayerByZ(0);
                int topIndex = topLayer.getXIndexOf(xValue);
                int startIndex = (int)Math.Floor(chartCtrl.getValueAtViewPort("x", chartCtrl.ViewPortLeft));
                int curIndex = topIndex + startIndex + mExtraPoints;
                if (curIndex >= 0 && curIndex < mCpDataSetObj.FutureData.Time.Length)
                {
                    double curTime = mCpDataSetObj.FutureData.Time[curIndex];
                    string sTime = GTGlobal.StockTimeToSysTime(curTime);
                    // Draw x-axis label
                    //label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + c.formatValue(curTime, "{value|P4}") + "<*/*>";
                    label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + sTime + "<*/*>";
                    tAxis = d.text(label, "Arial Bold", 8);
                    tAxis.draw(mouseX, plotArea.getBottomY() + 5, 0x000000, Chart.Top);
                }

                // label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + c.formatValue( mouseX, "MouseX = {value|P4}") + c.formatValue( mouseY, "MouseY = {value|P4}") + "<*/*>";
                // TTFText txtMouse = d.text(label, "Arial Bold", 8);
                // txtMouse.draw(plotArea.getLeftX() + 100, plotArea.getTopY() - 30, 0x000000, Chart.Right);
            }
        }


        private void chartCtrl_ViewPortChanged(object sender, ChartDirector.WinViewPortEventArgs e)
        {
            // In addition to updating the chart, we may also need to update other controls that
            // changes based on the view port.
            updateControls(chartCtrl);

            if (hasFinishedInitialization)
                drawChart(chartCtrl);

            // We need to update the track line too. If the mouse is moving on the chart (eg. if 
            // the user drags the mouse on the chart to scroll it), the track line will be updated
            // in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
            if (mClosing == false && (!chartCtrl.IsInMouseMoveEvent) && chartCtrl.IsMouseOnPlotArea)
            {
                WinChartViewer viewer = (WinChartViewer)sender;
                trackFinance((MultiChart)viewer.Chart, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY);
                chartCtrl.updateDisplay();
            }
        }

        private void chartCtrl_Paint(object sender, PaintEventArgs e)
        {
            ;
        }

        // Variable to save the original active control
        private Control activeControl = null;

        private void chartCtrl_MouseWheel(object sender, MouseEventArgs e)
        {
            // We zoom in or out by 10% depending on the mouse wheel direction.
            //double r = e.Delta > 0 ? 0.9 : 1 / 0.9;
            // We do not zoom in beyond the zoom in width limit.
            //if ((r = Math.Max(r, chartCtrl.ZoomInWidthLimit / chartCtrl.ViewPortWidth)) == 1)
            //    return;

            // We zoom in or out by 10% depending on the mouse wheel direction.
            double rx = e.Delta > 0 ? 0.9 : 1 / 0.9;
            double ry = rx;

            // We do not zoom in beyond the zoom in width or height limit.
            rx = Math.Max(rx, chartCtrl.ZoomInWidthLimit / chartCtrl.ViewPortWidth);
            ry = Math.Max(ry, chartCtrl.ZoomInWidthLimit / chartCtrl.ViewPortHeight);
            if ((rx == 1) && (ry == 1))
                return;

            //XYChart c = (XYChart)chartCtrl.Chart;
            FinanceChart c = (FinanceChart)chartCtrl.Chart;
            XYChart m = (XYChart)c.getChart(0);

  
            double mouseOffset = (chartCtrl.ChartMouseX - m.getPlotArea().getLeftX()) /
                (double)m.getPlotArea().getWidth();
            chartCtrl.ViewPortLeft += mouseOffset * (1 - rx) * chartCtrl.ViewPortWidth;
            chartCtrl.ViewPortWidth *= rx;

            double mouseOffsetY = (chartCtrl.ChartMouseY - m.getPlotArea().getTopY()) /
                (double)m.getPlotArea().getHeight();
            chartCtrl.ViewPortTop += mouseOffsetY * (1 - ry) * chartCtrl.ViewPortHeight;
            chartCtrl.ViewPortHeight *= ry;

            // Trigger a view port changed event to update the chart
            chartCtrl.updateViewPort(true, false);
        }

        private void hChartCtrlScrollBar_ValueChanged(object sender, EventArgs e)
        {
            // When the view port is changed (user drags on the chart to scroll), the scroll bar will get
            // updated. When the scroll bar changes (eg. user drags on the scroll bar), the view port will
            // get updated. This creates an infinite loop. To avoid this, the scroll bar can update the 
            // view port only if the view port is not updating the scroll bar.
            if (hasFinishedInitialization && !chartCtrl.IsInViewPortChangedEvent)
            {
                // Set the view port based on the scroll bar
                chartCtrl.ViewPortLeft = ((double)(hChartScrollBar.Value - hChartScrollBar.Minimum))
                    / (hChartScrollBar.Maximum - hChartScrollBar.Minimum);

                // Trigger a view port changed event to update the chart
                chartCtrl.updateViewPort(true, false);
            }
        }

        //
        // Update controls when the view port changed
        //
        private void updateControls(WinChartViewer viewer)
        {
            // Update the start date and end date control to reflect the view port.
            //startDateCtrl.Value = Chart.NTime(viewer.getValueAtViewPort("x", viewer.ViewPortLeft));
            //endDateCtrl.Value = Chart.NTime(viewer.getValueAtViewPort("x", viewer.ViewPortLeft +
            //    viewer.ViewPortWidth));

            // Update the scroll bar to reflect the view port position and width of the view port.
            hChartScrollBar.Enabled = chartCtrl.ViewPortWidth < 1;
            hChartScrollBar.LargeChange = (int)Math.Ceiling(chartCtrl.ViewPortWidth * (hChartScrollBar.Maximum - hChartScrollBar.Minimum));
            hChartScrollBar.SmallChange = (int)Math.Ceiling(hChartScrollBar.LargeChange * 0.1);
            hChartScrollBar.Value = (int)Math.Round(chartCtrl.ViewPortLeft * (hChartScrollBar.Maximum - hChartScrollBar.Minimum)) + hChartScrollBar.Minimum;
            //hChartScrollBar.Value = hChartScrollBar.Maximum;
        }
             
        /**
         * @brief 차트 확대 축소에 대한 기본적인 사항을 초기화 한다.
         * @param viewer : 차트 뷰어 컨트롤
         * @remark 차트 뷰어에 속한 전체 범위 설정, 최초 뷰 포트 너비, 좌우측 경계 및 최대 확대 영역 제한을 설정한다.
         */
        private void initChartViewer(WinChartViewer viewer)
        {
            // Set the full x range to be the duration of the data
            // 전체 범위를 나타낸다. 맨앞의 문자열은 범위를 표시하는 고유 문자열이며, 나머지 두 매개변수는 최소값과 최대값을 나타낸다.
            viewer.setFullRange("x", 0, mCpDataSetObj.FutureData.cTime.Length - 1);

            // Initialize the view port to show the latest 20% of the time range
            // 최초 표시 범위
            viewer.ViewPortWidth = 0.2;
            // 최초 표시 시작 점
            viewer.ViewPortLeft = 1 - viewer.ViewPortWidth;

            // 전체 범위에 대한 부분 범위를 나타낸다. 예를 들면 x데이터가 450개일 경우 10/450 이면 0.02%정도 된다.
            viewer.ZoomInWidthLimit = 10.0 / mCpDataSetObj.FutureData.cTime.Length;

            // Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
            //pointerPB.Checked = true;
        }

        /// <summary>
        /// Draw the chart according to user selection and display it in the WinChartViewer.
        /// </summary>
        /// <param name="viewer">The WinChartViewer object to display the chart.</param>
        private void drawChart(WinChartViewer viewer)
        {

            // Get the array indexes that corresponds to the visible start and end dates
            int startIndex = (int)Math.Floor(viewer.getValueAtViewPort("x", viewer.ViewPortLeft));
            int endIndex = (int)Math.Ceiling(viewer.getValueAtViewPort("x", viewer.ViewPortLeft + viewer.ViewPortWidth));
            int noOfPoints = endIndex - startIndex + 1;

            if (comboSource.SelectedIndex == 0)
            {
                // Extract the part of the data array that are visible.
                dataSTime = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.Time, startIndex, noOfPoints);
                dataHigh = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.High, startIndex, noOfPoints);
                dataLow = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.Low, startIndex, noOfPoints);
                dataClose = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.Close, startIndex, noOfPoints);
                dataOpen = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.Open, startIndex, noOfPoints);
                dataAmount = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.Amount, startIndex, noOfPoints);
                dataCTime = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.cTime, startIndex, noOfPoints);
                dataSysTime = (DateTime[])Chart.arraySlice(mCpDataSetObj.FutureData.DT, startIndex, noOfPoints);
            }
            else
            {
                dataSTime = (double[])Chart.arraySlice(mCpDataSetObj.CmeData.Time, startIndex, noOfPoints);
                dataHigh = (double[])Chart.arraySlice(mCpDataSetObj.CmeData.High, startIndex, noOfPoints);
                dataLow = (double[])Chart.arraySlice(mCpDataSetObj.CmeData.Low, startIndex, noOfPoints);
                dataClose = (double[])Chart.arraySlice(mCpDataSetObj.CmeData.Close, startIndex, noOfPoints);
                dataOpen = (double[])Chart.arraySlice(mCpDataSetObj.CmeData.Open, startIndex, noOfPoints);
                dataAmount = (double[])Chart.arraySlice(mCpDataSetObj.CmeData.Amount, startIndex, noOfPoints);
                dataCTime = (double[])Chart.arraySlice(mCpDataSetObj.CmeData.cTime, startIndex, noOfPoints);
            }

            m_WaveMgr.MakeUpDowPointList(mCpDataSetObj.FutureData.MA3);
            m_WaveMgr.FindRealWavePoint(mCpDataSetObj.FutureData.High, mCpDataSetObj.FutureData.Low);
            m_WaveMgr.FindTrendLine();

            //double r = 0.0, prob1 = 0.0, prob2 = 0.0, z = 0.0;
            //GTUtil.GTStat.GetPearson(dataCTime, dataClose, ref r, ref prob1, ref prob2, ref z);
            //GTUtil.GTStat.get_correlation(dataCTime, dataClose, ref r, ref prob1, ref prob2, ref z);

            //double r1 = r;

            
            // We need extra leading data points in order to compute moving averages.
            //int extraPoints = 20;

            // Create the chart object using the selected size
            FinanceChart m = new FinanceChart(panelBody.Width);
            //FinanceChart m = new FinanceChart(800);


            m.setData(dataCTime, dataHigh, dataLow, dataOpen, dataClose, dataAmount, mExtraPoints);

            //
            // We configure the title of the chart. In this demo chart design, we put the 
            // company name as the top line of the title with left alignment.
            //

            // 선택된 항목의 코드를 보여준다.
            //if (comboOpCode.SelectedIndex >= 0)
            //{
            //    string selectedItem = comboOpCode.Items[comboOpCode.SelectedIndex].ToString();
            //    m.addPlotAreaTitle(Chart.TopLeft, selectedItem);
            //}


            // A copyright message at the bottom left corner the title area
            m.addPlotAreaTitle(Chart.BottomRight, "<*font=arial.ttf,size=8*>Good Trader Engineering");


            XYChart mainChart = m.addMainChart(panelBody.Height);
            //mainChart.setPlotArea(50, 50, mainChart.getWidth(), mainChart.getHeight() - hChartScrollBar.Height);
            mainChart.setPlotArea(50, 50, chartCtrl.Width - 100, chartCtrl.Height - 160, 0xffffff, -1, 0xc0c0c0, 0xc0c0c0, -1);

            

            //DrawArea d = m.initDynamicLayer();
            //d.line(0, 0, 100, 100, 100, 2);

            // Add a 10 period simple moving average to the main chart, using brown color
            LineLayer mvLayer = m.addSimpleMovingAvg(5, 0x663300);
            //ChartDirector.DataSet mvDataSet = mvLayer.getDataSet(0);
            //double aval = mvDataSet.getValue(0);

            //double mv = aval;
            //m.addVolBars(300, 0xff0000, 0x0000ff, 0x00ff00);

            //m.addBand(dataHigh, dataLow, 0x99ff99, 0x99ff99, "UpperZone");
            
            /*
            LineLayer lineLayer = mainChart.addLineLayer();
            lineLayer.addDataSet(dataHigh, 0x338033, "Target Zone");
            lineLayer.addDataSet(dataLow, 0x338033);
            lineLayer.setXData(dataCTime);
            lineLayer.setLineWidth(2);
             */
              

            // Color the zone between the upper zone line and lower zone line as
            // semi-transparent light green (8099ff99)
            //mainChart.addInterLineLayer(lineLayer.getLine(0), lineLayer.getLine(1), 0, 0);



            // Add a 20 period simple moving average to the main chart, using purple color
            m.addSimpleMovingAvg(20, 0x9900ff);

            // Add 20 days bollinger band to the main chart, using light blue (9999ff) as the border and
            // semi-transparent blue (c06666ff) as the fill color
            //m.addBollingerBand(20, 2, 0x9999ff, unchecked((int)0xc06666ff));

            double[] ma = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.MA3, startIndex, noOfPoints);
            LineLayer la2 = mainChart.addLineLayer(ma, 0xffff00, "MACD2");
            la2.setLineWidth(3);

            double[] data0Y = { 258.62, 255.69, 255.53, 255.58, 255.84, 255.76, 255.49, 256.61, 256.64, 256.77, 255.79 };
            int[] data0X = { 100, 111, 123, 134, 156, 178, 189, 200, 201, 202, 206};
            //LineLayer la = mainChart.addLineLayer(data0Y, 0xffff00, "MACD");
            //la.setLineWidth(3);

            //LineLayer la = mainChart.addLineLayer(data0Y, 0xff00ff, "Nice");
           
            //LineLayer layer0 = mainChart.addLineLayer2();
            //layer0.addDataSet(data0Y, 0xff0000, "Quantum Computer").setDataSymbol(
            //    Chart.GlassSphere2Shape, 11);
            //double[] dataX = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.cTime, endIndex - 11, 11);
            //layer0.setXData2(mCpDataSetObj.FutureData.cTime[200], mCpDataSetObj.FutureData.cTime[210]);
            //DateTime data2Start = new DateTime(2014, 4, 30);
            //DateTime data2End = new DateTime(2014, 5, 2);
            //layer0.setXData(data0X);
            //layer0.setXData2(1, 333);
            //layer0.setLineWidth(3);

            //LineLayer li3 = m.addLineIndicator2(mainChart, data0Y, 0xff0000, "Nice");
            //li3.setXData(data0X);
            


            //double[] dayIndex = (double[])Chart.arraySlice(mCpDataSetObj.FutureData.DayIndex, startIndex, noOfPoints);
            //LineLayer la2 = mainChart.addLineLayer(dayIndex, 0x000000, "DayIndex");
            //la2.setLineWidth(3);


            // Add a 75 pixels volume bars sub-chart to the bottom of the main chart, using green/red/grey for
            // up/down/flat days
            //m.addVolBars(75, 0x99ff99, 0xff9999, 0x808080);

            // Append a MACD(26, 12) indicator chart (75 pixels high) after the main chart, using 9 days for
            // computing divergence.
            //m.addMACD(75, 26, 12, 9, 0x0000ff, 0xff00ff, 0x008000);

            CandleStickLayer clayer = m.addCandleStick(0xff3333, 0x33ff33);
            clayer.addDataSet(dataClose);

                                   
            double hMin = 0.0, hMax = 0.0;
            double lMin = 0.0, lMax = 0.0;
            if (comboSource.SelectedIndex == 0)
            {
                GTGlobal.FindMinMax(mCpDataSetObj.FutureData.High, ref hMin, ref hMax);
                GTGlobal.FindMinMax(mCpDataSetObj.FutureData.Low, ref lMin, ref lMax);
            }
            else
            {
                GTGlobal.FindMinMax(mCpDataSetObj.CmeData.High, ref hMin, ref hMax);
                GTGlobal.FindMinMax(mCpDataSetObj.CmeData.Low, ref lMin, ref lMax);
            }
            double tMin = Math.Min(hMin, lMin);
            double tMax = Math.Max(hMax, lMax);

            //mainChart.yAxis().setLinearScale(tMin, tMax, 5.0, 2.5);

            //
            // Draw candlesticks or OHLC symbols if the user has selected them.
            //
            


            //viewer.syncLinearAxisWithViewPort("x", mainChart.xAxis());
            //viewer.syncLinearAxisWithViewPort("y", mainChart.yAxis());
            //
            // output the chart
            //

            DrawArea d = mainChart.makeChart3();

            //DrawArea d = c.makeChart3();
            //d.hFlip();

            //d.line(0, 0, 800, 800, 255, 3);

            


            int index = mCpDataSetObj.FutureData.FindIndex(20140502, GTGlobal.TimeToInt(9, 40));


            PlotArea plotArea = mainChart.getPlotArea();
            int offsetX = mainChart.getAbsOffsetX();
            int offsetY = mainChart.getAbsOffsetY();
            int plotAreaLeftX = plotArea.getLeftX() + offsetX;
            int plotAreaTopY = plotArea.getTopY() + offsetY;


            int plotHeight = plotArea.getHeight();
            int plotWidth = plotArea.getWidth();
            int width = plotWidth + 0;


            //d.vline(plotAreaTopY, plotAreaTopY + plotHeight, c.getXCoor(xValue) + c.getAbsOffsetX(), d.dashLineColor(0x000000, 0x0101));
            //d.hline(plotArea.getLeftX(), plotArea.getRightX(), c.getYCoor(yValue) + c.getAbsOffsetY(), d.dashLineColor(0x000000, 0x0101));
            // Draw a vertical track line at the x-position
            /*
            d.vline(plotAreaTopY, plotAreaTopY + plotArea.getHeight(), mainChart.getXCoor(index - startIndex - mExtraPoints) +
                mainChart.getAbsOffsetX(), d.dashLineColor(0xff0000, 0x0101));

            d.line(mainChart.getXCoor(index - startIndex - mExtraPoints) + mainChart.getAbsOffsetX(), 0, mainChart.getXCoor(index - startIndex - mExtraPoints) + mainChart.getAbsOffsetX(), 800, 255, 3);
            double yval = 256.7;
            double[] yp = new double[4] { mainChart.getYCoor(yval) + mainChart.getAbsOffsetY(), mainChart.getYCoor(yval) + mainChart.getAbsOffsetY(), mainChart.getYCoor(yval) + mainChart.getAbsOffsetY() + 50, mainChart.getYCoor(yval) + mainChart.getAbsOffsetY() + 50 };
            double[] xp = new double[4] { mainChart.getXCoor(index - startIndex - mExtraPoints) + mainChart.getAbsOffsetX(), mainChart.getXCoor(index - startIndex - mExtraPoints) + mainChart.getAbsOffsetX() + 50, mainChart.getXCoor(index - startIndex - mExtraPoints) + mainChart.getAbsOffsetX() + 50, mainChart.getXCoor(index - startIndex - mExtraPoints) + mainChart.getAbsOffsetX() };
            d.polygon(xp, yp, 255, 355);
             */
            DrawArrow(mainChart, index - startIndex - mExtraPoints, 257.0, 20, -1);
            DrawArrow(mainChart, index - startIndex - mExtraPoints, 256.0, 20, 1);

            for (int k = 0; k < m_WaveMgr.WaveList.Count; k++)
            {
                if (k + 1 < m_WaveMgr.WaveList.Count)
                {
                    GTWave.GTPoint pt1 = m_WaveMgr.WaveList[k];
                    GTWave.GTPoint pt2 = m_WaveMgr.WaveList[k + 1];

                    DrawLine(mainChart, pt1.X - startIndex - mExtraPoints, pt1.Y, pt2.X - startIndex - mExtraPoints, pt2.Y, 0x000000);
                    d.text((k - 1).ToString(), "Arial", 10, mainChart.getXCoor(pt1.X - startIndex - mExtraPoints) + mainChart.getAbsOffsetX() , mainChart.getYCoor(pt1.Y) + mainChart.getAbsOffsetY(), 0x000000FF);
                }
            }

            for (int k = 0; k < m_WaveMgr.TrendLineList.Count; k++)
            {
                if (m_TrendIndex != -1 && m_TrendIndex == k && k + 1 < m_WaveMgr.TrendLineList.Count)
                {
                    GTWave.GTTrendLine tLine = m_WaveMgr.TrendLineList[k];

                    DrawLine(mainChart, tLine.SP.X - startIndex - mExtraPoints, tLine.SP.Y, tLine.Near.X - startIndex - mExtraPoints, tLine.Near.Y, 0x000000);
                    DrawLine(mainChart, tLine.SP.X - startIndex - mExtraPoints, tLine.SP.Y, tLine.Far.X - startIndex - mExtraPoints, tLine.Far.Y, 0xff0000);
                    DrawLine(mainChart, tLine.SP.X - startIndex - mExtraPoints, tLine.SP.Y, tLine.MuchFar.X - startIndex - mExtraPoints, tLine.MuchFar.Y, 0x00ff00);
                }
            }

            viewer.Chart = m;
            //DrawTriangle(viewer);
            //
            // tooltips for the chart
            //
            viewer.ImageMap = m.getHTMLImageMap("", "", "title='" + m.getToolTipDateFormat() + " {value|P}'");
            if (mClosing == false)
                trackFinance((MultiChart)viewer.Chart, viewer.IsMouseOnPlotArea ? viewer.PlotAreaMouseX : mainChart.getPlotArea().getRightX(), viewer.PlotAreaMouseY);
        }

        /**
         * @breif 이 함수는 주어진 좌표에 화살표를 그린다.
         * @aChart : 화살표를 그릴 차트 객체
         * @param aX : X좌표. 정수로써 현재 차트에서 X축 인덱스를 가리킨다.
         * @param aY : Y좌표. 실수로서 Y값을 가리킨다.
         * @param aSize : 화살표의 한변 길이로 픽셀 단위이다.
         * @param aDirec : 화살표의 방향을 가리킨다. -1 : 아래로, 1 : 위로, -2 : 왼쪽으로, 2 : 오른쪽으로
         */
        private void DrawArrow(XYChart aChart, int aX,  double aY, int aSize, int aDirec)
        {
            DrawArea d = aChart.makeChart3();

            // 모든 점들은 중심점에서 출발한다. 중심점에서 시계방향으로 돈다.
            if (aDirec == -1)
            {
                double[] xp = new double[3] { aChart.getXCoor(aX) + aChart.getAbsOffsetX(), aChart.getXCoor(aX) + aChart.getAbsOffsetX() - aSize / 2, aChart.getXCoor(aX) +aChart.getAbsOffsetX() + aSize / 2 };
                double[] yp = new double[3] { aChart.getYCoor(aY) + aChart.getAbsOffsetY(), aChart.getYCoor(aY) + aChart.getAbsOffsetY() - Math.Sqrt(3) * aSize / 2, aChart.getYCoor(aY) + aChart.getAbsOffsetY() - Math.Sqrt(3) * aSize / 2 };
                d.polygon(xp, yp, 0x000000FF, 0x000000FF);
                d.text("매도", "Arial", 10, aChart.getXCoor(aX) + aChart.getAbsOffsetX() + aSize / 2, aChart.getYCoor(aY) + aChart.getAbsOffsetY() - (int)(Math.Sqrt(3) * aSize / 2), 0x000000FF);
            }
            else if (aDirec == 1)
            {
                double[] xp = new double[3] { aChart.getXCoor(aX) + aChart.getAbsOffsetX(), aChart.getXCoor(aX) + aChart.getAbsOffsetX() + aSize / 2, aChart.getXCoor(aX) + aChart.getAbsOffsetX() - aSize / 2 };
                double[] yp = new double[3] { aChart.getYCoor(aY) + aChart.getAbsOffsetY(), aChart.getYCoor(aY) + aChart.getAbsOffsetY() + Math.Sqrt(3) * aSize / 2, aChart.getYCoor(aY) + aChart.getAbsOffsetY() + Math.Sqrt(3) * aSize / 2 };
                d.polygon(xp, yp, 0x00FF0000, 0x00FF0000);
                d.text("매수", "Arial", 10, aChart.getXCoor(aX) + aChart.getAbsOffsetX() + aSize / 2, aChart.getYCoor(aY) + aChart.getAbsOffsetY(), 0x00FF0000);
            }
            else if (aDirec == 2)
            {
                double[] xp = new double[3] { aChart.getXCoor(aX) + aChart.getAbsOffsetX(), aChart.getXCoor(aX) + aChart.getAbsOffsetX() - aSize * Math.Sqrt(3) / 2, aChart.getXCoor(aX) + aChart.getAbsOffsetX() - aSize * Math.Sqrt(3) / 2 };
                double[] yp = new double[3] { aChart.getYCoor(aY) + aChart.getAbsOffsetY(), aChart.getYCoor(aY) + aChart.getAbsOffsetY() + aSize / 2, aChart.getYCoor(aY) + aChart.getAbsOffsetY() - aSize / 2 };
                d.polygon(xp, yp, 0x00FF0000, 0x00FF0000);
            }
            else if (aDirec == -2)
            {
                double[] xp = new double[3] { aChart.getXCoor(aX) + aChart.getAbsOffsetX(), aChart.getXCoor(aX) + aChart.getAbsOffsetX() + aSize * Math.Sqrt(3) / 2, aChart.getXCoor(aX) + aChart.getAbsOffsetX() + aSize * Math.Sqrt(3) / 2 };
                double[] yp = new double[3] { aChart.getYCoor(aY) + aChart.getAbsOffsetY(), aChart.getYCoor(aY) + aChart.getAbsOffsetY() - aSize / 2, aChart.getYCoor(aY) + aChart.getAbsOffsetY() + aSize / 2 };
                d.polygon(xp, yp, 0x000000FF, 0x000000FF);
            }
        }


        private void DrawLine(XYChart aChart, int aX1, double aY1, int aX2, double aY2, int aColor)
        {
            DrawArea d = aChart.makeChart3();
            d.line(aChart.getXCoor(aX1) + aChart.getAbsOffsetX(), aChart.getYCoor(aY1) + aChart.getAbsOffsetY(), aChart.getXCoor(aX2) + aChart.getAbsOffsetX(), aChart.getYCoor(aY2) + aChart.getAbsOffsetY(), aColor, 2);
        }

        private void DrawTriangle(WinChartViewer viewer)
        {
            MultiChart m = (MultiChart)viewer.Chart;
            XYChart c = (XYChart)m.getChart(0);
            DrawArea d = c.getDrawArea();

            //DrawArea d = c.makeChart3();
            //d.hFlip();

            d.line(0, 0, 800, 800, 255, 3);
        }

        protected void errMsg(WinChartViewer viewer, string msg)
        {
            MultiChart m = new MultiChart(400, 200);
            m.addTitle2(Chart.Center, msg, "Arial", 10).setMaxWidth(m.getWidth());
            viewer.Image = m.makeImage();
        }

        private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
        private void InitTimer()
        {
            timer.Interval = 1000;
            timer.Tick += new EventHandler(OnTimerTick);
            timer.Start();
        }

        private void OnTimerTick(object sender, EventArgs e)
        {
            DateTime curDate = DateTime.Now;
            string topLabelText = "현재시간 : ";
            topLabelText += curDate.Year.ToString() + "년";
            topLabelText += curDate.Month.ToString() + "월";
            topLabelText += curDate.Day.ToString() + "일";
            topLabelText += curDate.Hour.ToString() + "시";
            topLabelText += curDate.Minute.ToString() + "분";
            topLabelText += curDate.Second.ToString() + "초";

            topLabel.Text = topLabelText;
            //if (hasFinishedInitialization)
            //    drawChart(chartCtrl);
            // Trigger a view port changed event to update the chart
            chartCtrl.updateViewPort(true, false);
        }

        private void panelBody_Resize(object sender, EventArgs e)
        {
            ;
        }

        private void hChartScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            ;
        }

        private void comboOpCode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboSource.SelectedIndex >= 0)
            {
                // 데이터를 대응 시켜준다.
                mIndex = comboSource.SelectedIndex;
                // 차트 컨트롤을 갱신시켜서 새로운 차트를 볼 수 있게 한다.
                chartCtrl.updateViewPort(true, false);
            }
        }

        private bool mClosing = false;
        private void frmFutureChart_FormClosing(object sender, FormClosingEventArgs e)
        {
            mClosing = true;
        }
        private int m_TrendIndex = 0;
        private void comboTrendLine_SelectedIndexChanged(object sender, EventArgs e)
        {
            m_TrendIndex = comboTrendLine.SelectedIndex;
            if (m_TrendIndex > 0)
                chartCtrl.updateViewPort(true, false);
        }
    }
}
